﻿using System;
using System.ComponentModel;
using System.IO;
using System.IO.Compression;
using System.Windows.Forms;
using DICOMViewer.UC;
using Leadtools.Dicom;
using qiniu_class.Storage;

namespace DICOMViewer.Utility
{
    public class ZipFileConverter
    {
        private readonly BackgroundWorker converter = new BackgroundWorker();
        private readonly string desZipFile;
        private readonly string[] dicomFiles;
        private readonly string rootDir;
        private readonly string orderNumber;
        private readonly string sourceZipFile;

        public ZipFileConverter()
        {
            converter.WorkerReportsProgress = true;
            converter.ProgressChanged += Converter_ProgressChanged;
            converter.RunWorkerCompleted += Converter_RunWorkerCompleted;
        }

        public ZipFileConverter(string sourceZipFile, string desZipFile, string orderNumber
            , ProgressForm progressForm) : this()
        {
            this.orderNumber = orderNumber;
            this.sourceZipFile = sourceZipFile;
            this.desZipFile = desZipFile;
            this.progressForm = progressForm;
            converter.DoWork += Converter_DoZipConvertWork;
        }
        public ZipFileConverter(string[] dicomFiles,string rootDir, string desZipFile, string orderNumber
    , ProgressForm progressForm) : this()
        {
            this.orderNumber = orderNumber;
            this.dicomFiles = dicomFiles;
            this.rootDir = rootDir;
            this.desZipFile = desZipFile;
            this.progressForm = progressForm;
            converter.DoWork += Converter_DoDicomFilesWork;
        }

        private void Converter_DoDicomFilesWork(object sender, DoWorkEventArgs e)
        {
            progressForm.Invoke(new EventHandler(delegate
            {
                progressForm.progressCounter.Maximum = dicomFiles.Length + 2;
            }));
            ZipEx zipex = new ZipEx();
            zipex.InitZip(desZipFile);
            var i = 1;
            converter.ReportProgress(i);
            var studyInstanceUID = string.Empty;
            foreach (string path in dicomFiles)
            {
                DicomDataSet ds = new DicomDataSet();
                Stream stream;
                Console.WriteLine(path);
                if (path.EndsWith("DICOMDIR")) continue;
                stream = File.Open(path,FileMode.Open);
                string filesPath = path.Replace(rootDir, string.Empty);
                try
                {
                    //判定是否dicom文件，如果不是直接存入压缩包
                    if (!DicomDirMaker.isDicom(stream))
                    {
                        Console.WriteLine("{0} is not a Dicom file!", path);
                        zipex.AppendZipFile(stream, filesPath);
                        //主要为发生DicomDataSet的load操作不支持，即文件不是dcm文件时跳过文件
                        continue;
                    }
                    string sopInstanceUID;
                    if (e.Result == null)
                    {
                        sopInstanceUID = DicomDataMaskUtility.DicomDataMask(orderNumber, ds, stream, out studyInstanceUID);
                        if (!string.IsNullOrEmpty(studyInstanceUID)) e.Result = studyInstanceUID;
                    }
                    else
                    {
                        sopInstanceUID = DicomDataMaskUtility.DicomDataMask(orderNumber, ds, stream);
                    }

                    //压缩为Jpeg2000格式
                    ImageConverter.ConvertJpeg2000(ds);
                    //保存到内存流
                    MemoryStream mstream = new MemoryStream();
                    ds.Save(mstream, DicomDataSetSaveFlags.None);
                    //修改文件名为SopInstanceUID，并将数据保存到新zip文件
                    var filename = Path.GetFileNameWithoutExtension(path.Replace(rootDir, string.Empty));
                    zipex.AppendZipFile(mstream, filesPath.Replace(filename, sopInstanceUID));
                }
                catch (NotSupportedException)
                {
                    //主要为发生DicomDataSet的load操作不支持，即文件不是dcm文件时跳过文件
                    zipex.AppendZipFile(stream, filesPath);
                }
                catch (DicomException ex)
                {
                    if (ex.Code == DicomExceptionCode.Format)
                    {
                        //主要为发生DicomDataSet的load操作不支持，即文件不是dcm文件时跳过文件
                        zipex.AppendZipFile(stream, filesPath);
                    }
                    else
                    {
                        throw ex;
                    }
                }
                finally
                {
                    ds.Dispose();
                    i++;
                    //通报进展，引发ProgressChanged事件
                    converter.ReportProgress(i);
                }
            }
            zipex.OutPut();
            i++;
            //通报进展，引发ProgressChanged事件
            converter.ReportProgress(i);
        }

        public ProgressForm progressForm { get; set; }

        public void beginConvert()
        {
            converter.RunWorkerAsync();
        }

        public event RunWorkerCompletedEventHandler OnConverCompleted
        {
            add { converter.RunWorkerCompleted += value; }
            remove { converter.RunWorkerCompleted -= value; }
        }

        private void Converter_DoZipConvertWork(object sender, DoWorkEventArgs e)
        {
            ZipArchive archive = ZipFile.Open(sourceZipFile, ZipArchiveMode.Update);
            progressForm.Invoke(new EventHandler(delegate
            {
                progressForm.progressCounter.Maximum = archive.Entries.Count + 2;
            }));
            ZipEx zipex = new ZipEx();
            zipex.InitZip(desZipFile);
            var i = 1;
            converter.ReportProgress(i);
            var studyInstanceUID = string.Empty;
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                DicomDataSet ds = new DicomDataSet();
                Stream stream;
                Console.WriteLine(entry.FullName);
                if (entry.FullName.EndsWith("/")) continue;
                if (entry.FullName.EndsWith("DICOMDIR")) continue;
                stream = entry.Open();
                try
                {
                    //判定是否dicom文件，如果不是直接存入压缩包
                    if (!DicomDirMaker.isDicom(stream))
                    {
                        Console.WriteLine("{0} is not a Dicom file!", entry.FullName);
                        zipex.AppendZipFile(stream, entry.FullName);
                        //主要为发生DicomDataSet的load操作不支持，即文件不是dcm文件时跳过文件
                        continue;
                    }
                    string sopInstanceUID;
                    if (e.Result == null)
                    {
                        sopInstanceUID = DicomDataMaskUtility.DicomDataMask(orderNumber, ds, stream, out studyInstanceUID);
                        if (!string.IsNullOrEmpty(studyInstanceUID)) e.Result = studyInstanceUID;
                    }
                    else
                    {
                        sopInstanceUID = DicomDataMaskUtility.DicomDataMask(orderNumber, ds, stream);
                    }
                    
                    //压缩为Jpeg2000格式
                    ImageConverter.ConvertJpeg2000(ds);
                    //保存到内存流
                    MemoryStream mstream = new MemoryStream();
                    ds.Save(mstream, DicomDataSetSaveFlags.None);
                    //修改文件名为SopInstanceUID，并将数据保存到新zip文件
                    var filename = Path.GetFileNameWithoutExtension(entry.FullName);
                    zipex.AppendZipFile(mstream, entry.FullName.Replace(filename, sopInstanceUID));
                }
                catch (NotSupportedException)
                {
                    //主要为发生DicomDataSet的load操作不支持，即文件不是dcm文件时跳过文件
                    zipex.AppendZipFile(stream, entry.FullName);
                }
                catch (DicomException ex)
                {
                    if (ex.Code == DicomExceptionCode.Format)
                    {
                        //主要为发生DicomDataSet的load操作不支持，即文件不是dcm文件时跳过文件
                        zipex.AppendZipFile(stream, entry.FullName);
                    }
                    else
                    {
                        throw ex;
                    }
                }
                finally
                {
                    ds.Dispose();
                    i++;
                    //通报进展，引发ProgressChanged事件
                    converter.ReportProgress(i);
                }
            }
            archive.Dispose();
            zipex.OutPut();
            i++;
            //通报进展，引发ProgressChanged事件
            converter.ReportProgress(i);
        }

        private void Converter_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressForm.DialogResult = DialogResult.OK;
            progressForm.Dispose();
        }

        private void Converter_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressForm.Invoke(new EventHandler((a, b) =>
            {
                progressForm.progressCounter.Value = e.ProgressPercentage;
                progressForm.counterLabel.Text = string.Format("正在制作数据... ( {0} % )",
                    e.ProgressPercentage*100/progressForm.progressCounter.Maximum);
            }));
        }
    }
}